package com.msh.platform.elm.controller;

import com.msh.platform.bizmedia.base.conf.ResponseResult;
import com.alibaba.fastjson.JSONObject;
import com.msh.platform.bizmedia.base.util.AliSmsTools;
import com.msh.platform.elm.common.constants.Constants;
import com.msh.platform.elm.common.constants.SmsType;
import com.msh.platform.elm.entity.CfgArea;
import com.msh.platform.elm.entity.SellerInfo;
import com.msh.platform.elm.entity.SmsInfo;
import com.msh.platform.elm.entity.WxPubNo;
import com.msh.platform.elm.entity.CfgMessage;
import com.msh.platform.elm.entity.SaleSpec;
import com.msh.platform.elm.service.CfgAreaService;
import com.msh.platform.elm.service.CfgMessageService;
import com.msh.platform.elm.service.OperLogService;
import com.msh.platform.elm.service.SaleSpecService;
import com.msh.platform.elm.service.SellerService;
import com.msh.platform.elm.service.SmsInfoService;
import com.msh.platform.elm.service.WxPubNoService;
import com.msh.platform.elm.vo.SellerInfoRqVO;
import com.msh.platform.elm.vo.SellerInfoRsVO;
import com.msh.platform.elm.vo.SendPhonCodeVO;
import com.msh.platform.elm.vo.WxPubNoRqVO;
import com.msh.platform.elm.vo.WxPubNoRsVO;
import com.msh.platform.elm.vo.PageVO;
import com.msh.platform.elm.vo.PubNoDqVO;
import com.msh.platform.elm.vo.TokenVO;
import com.msh.platform.elm.vo.LoginVO;
import com.msh.platform.elm.vo.ResetPasswdVO;
import com.msh.platform.elm.common.util.SortUtils;
import com.msh.platform.elm.common.util.MD5;
import com.msh.platform.elm.common.util.MapTrunPojoUtils;

import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.validation.Valid;

/**
 * @Author zhangyangsong
 * @Description :
 * @Date: Created in 2018/11/8
 * @Copyright: ©2018 all rights reserved.
 */
@RestController
@RequestMapping(value = "/seller")
@Api(tags = "商会管理接口")
@Slf4j
public class SellerController extends BaseController{
	
	@Autowired
	private SellerService sellerService;
	@Autowired
	private CfgAreaService cfgAreaService;
	@Autowired
	private CfgMessageService cfgMessageService;
	@Autowired
	private WxPubNoService wxPubNoService;
	@Autowired
	private SaleSpecService saleSpecService;
	@Autowired
	private SmsInfoService smsInfoService;
	@Autowired
	private OperLogService operLogService;
	@Autowired
    private RedisTemplate redisTemplate;
	@Autowired
    private AliSmsTools aliSmsTools;

    @ApiOperation(value = "商会用户登录")
    @PostMapping(path = "/login")
    public ResponseResult<SellerInfoRsVO> login(@RequestBody @Valid LoginVO paramVo, BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
	        return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	SellerInfoRsVO sellerVo = new SellerInfoRsVO();
		//校验sign字符串
    	Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.remove("sign");
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			String encPwdString = MD5.compile(paramVo.getPasswd() + Constants.PWD_MD5_KEY);
			SellerInfo seller = sellerService.getSeller(paramVo.getPhone(),encPwdString);
	    	if(seller!=null) {
	    		//生成token
				String token = UUID.randomUUID().toString();
				
				//将token跟用户信息一起写入redis并设置过期时间
				ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
	            operations.set(token, JSONObject.toJSONString(seller));
	            redisTemplate.expire(token, Constants.TOKEN_EXPIRE_TIME, TimeUnit.MINUTES);
				
				BeanUtils.copyProperties(seller,sellerVo);
				sellerVo.setToken(token);
	    		return ResponseResult.success(sellerVo);
	    	}else {
	    		return ResponseResult.fail(Constants.RESP_FAIL, "登录失败，用户名或密码错误");
	    	}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "商会用户注册")
    @PostMapping(path = "/register")
    public ResponseResult register(@RequestBody @Valid SellerInfoRqVO paramVo, BindingResult errors) {
		if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
			return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
		//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.remove("sign");
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			SmsInfo sms = smsInfoService.findFirstByPhone(paramVo.getPhone());
			if(sms!=null && paramVo.getSmsCode().equals(sms.getCode())) {
				SellerInfo seller = new SellerInfo();
		        BeanUtils.copyProperties(paramVo,seller);
	    		sellerService.saveSellerAndAcct(seller);
	    		return ResponseResult.success(null);
			}else {
				return ResponseResult.fail(Constants.RESP_FAIL, "验证码错误");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "重置密码")
    @PostMapping(path = "/reset_passwd")
    public ResponseResult reset_passwd(@RequestBody @Valid ResetPasswdVO paramVo, BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.remove("sign");
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
	    	SmsInfo sms = smsInfoService.findFirstByPhone(paramVo.getPhone());
	    	if(sms!=null && paramVo.getSmsCode().equals(sms.getCode())){
	    		SellerInfo seller = sellerService.findByPhone(paramVo.getPhone());
		    	if(seller!=null) {
		    		String encPwdString = MD5.compile(paramVo.getPasswd() + Constants.PWD_MD5_KEY);
		    		seller.setPasswd(encPwdString);
		    		sellerService.save(seller);
		    		return ResponseResult.success(null);
		    	}else {
		    		return ResponseResult.fail(Constants.RESP_FAIL, "重置密码失败，该手机号不存在");
		    	}
	    	}else {
	    		return ResponseResult.fail(Constants.RESP_FAIL, "短信验证码错误");
	    	}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "发送短信验证码")
    @PostMapping(path = "/send_sms_code")
    public ResponseResult send_sms_code(@RequestBody @Valid SendPhonCodeVO paramVo) {
    	//校验sign字符串
    	Map<String, Object> signMap = new HashMap<String,Object>();
    	signMap.put("phone", paramVo.getPhone());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			String phone = paramVo.getPhone();
	    	String smsCode = genRadomNbr();
	        String param = "{code:'" + smsCode + "'}";
	        String sendTempl = "SMS_94755132";
	        aliSmsTools.smsNumSendRequest(param,phone,sendTempl);
	        //将验证码跟手机号保存到短信表里
	        smsInfoService.saveSms(phone, null, smsCode, "", SmsType.smsCode.getCode());
			return ResponseResult.success(null);
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "获取省市县信息")
    @PostMapping(path = "/get_area_info/{pId}")
    @ApiImplicitParam(name="pId",value="地区父id,查省传100000，查市传所属省id，查区县传所属市id",required=true,paramType="path",dataType="int")
    public ResponseResult<List<CfgArea>> get_area_info(@PathVariable int pId, @RequestBody @Valid TokenVO paramVo, BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = new HashMap<String,Object>();
		signMap.put("pId", pId);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());  //通过token获取登录用户
			if(userObj!=null) {  //用户已登录
		    	List<CfgArea> areaList = cfgAreaService.findByPId(pId);
		    	return ResponseResult.success(areaList);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}	
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "获取消息列表")
    @PostMapping(path = "/get_message_page")
    public ResponseResult<Page<CfgMessage>> get_message_page(@RequestBody @Valid PageVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());  //通过token获取登录用户
			if(userObj!=null) {  //用户已登录
	    		JSONObject jsonObj = JSONObject.parseObject(userObj.toString());
	    		SellerInfo seller = JSONObject.toJavaObject(jsonObj, SellerInfo.class);
			
	    		Sort sort = new Sort(Sort.Direction.DESC,"createTime"); //创建时间降序排序
	    		Pageable pageable = PageRequest.of(paramVo.getPageNo(), paramVo.getPageSize(), sort);
	    		Page<CfgMessage> messages = cfgMessageService.findByUserId(seller.getId(), pageable);
	    		return ResponseResult.success(messages);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "获取商会公众号列表")
    @PostMapping(path = "/get_seller_pub_no_page")
    public ResponseResult<Page<WxPubNo>> get_seller_pub_no_page(@RequestBody @Valid PageVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
	    		JSONObject jsonObj = JSONObject.parseObject(userObj.toString());
	    		SellerInfo seller = JSONObject.toJavaObject(jsonObj, SellerInfo.class);
	    		
	    		Sort sort = new Sort(Sort.Direction.DESC,"createTime"); //创建时间降序排序
	    		Pageable pageable = PageRequest.of(paramVo.getPageNo(), paramVo.getPageSize(), sort);
	    		Page<WxPubNo> wxPubNoList = wxPubNoService.findBySellerId(seller.getId(), pageable);
	    		return ResponseResult.success(wxPubNoList);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "新增公众号")
    @PostMapping(path = "/add_pub_no")
    public ResponseResult add_pub_no(@RequestBody @Valid WxPubNoRqVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		List<PubNoDqVO> dqVOs = paramVo.getDqs();
		String dqParamStr = "";
		for(PubNoDqVO dqVO : dqVOs) {
			Map<String, Object> signDqMap = MapTrunPojoUtils.object2Map(dqVO);
			dqParamStr += SortUtils.sortMap(signDqMap);
		}
		signMap.remove("dqs");
		signMap.put("dqs", dqParamStr);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
				JSONObject jsonObj = JSONObject.parseObject(userObj.toString());
	    		SellerInfo seller = JSONObject.toJavaObject(jsonObj, SellerInfo.class);
	    		
	    		wxPubNoService.addWxPubNo(paramVo,seller.getId());
	    		return ResponseResult.success(null);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "获取公众号详情")
    @PostMapping(path = "/get_pub_no_detail/{id}")
    public ResponseResult<WxPubNoRsVO> get_pub_no_detail(@PathVariable int id,@RequestBody @Valid TokenVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }
    	//校验sign字符串
		Map<String, Object> signMap = new HashMap<String, Object>();
		signMap.put("id", id);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
				WxPubNoRsVO vo = wxPubNoService.getWxPubNoVO(id);
				return ResponseResult.success(vo);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "修改公众号")
    @PostMapping(path = "/edit_pub_no/{id}")
    public ResponseResult edit_pub_no(@PathVariable int id,@RequestBody @Valid WxPubNoRqVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }	
    	//校验sign字符串
		Map<String, Object> signMap = MapTrunPojoUtils.object2Map(paramVo);
		signMap.remove("dqs");
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
				JSONObject jsonObj = JSONObject.parseObject(userObj.toString());
	    		SellerInfo seller = JSONObject.toJavaObject(jsonObj, SellerInfo.class);
	    		
	    		wxPubNoService.editWxPubNo(paramVo,id,seller.getId());
	    		return ResponseResult.success(null);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}
    }
    
    @ApiOperation(value = "获取公众号版位信息")
    @PostMapping(path = "/get_pub_no_position")
    public ResponseResult<List<SaleSpec>> get_pub_no_position(@RequestBody @Valid TokenVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }	
    	//校验sign字符串
		Map<String, Object> signMap = new HashMap<String, Object>();
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
	    		List<SaleSpec> specList = saleSpecService.findAll();
	    		return ResponseResult.success(specList);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}	
    }
    
    @ApiOperation(value = "下架公众号")
    @PostMapping(path = "/down_pub_no/{id}")
    public ResponseResult down_pub_no(@PathVariable int id,@RequestBody @Valid TokenVO paramVo,BindingResult errors) {
    	if (errors.hasErrors()){  //参数校验失败
			//返回参数校验错误信息
    		return ResponseResult.fail(Constants.RESP_FAIL, errors.getAllErrors().get(0).getDefaultMessage());
	    }	
    	//校验sign字符串
		Map<String, Object> signMap = new HashMap<String, Object>();;
		signMap.put("id", id);
		signMap.put("token", paramVo.getToken());
		String paramStr = SortUtils.sortMap(signMap);
		boolean flag = validateSign(paramStr, paramVo.getSign());
		log.info("验证签名结果：" + flag);
		if(flag){
			Object userObj = getUserByToken(paramVo.getToken());
			if(userObj!=null) {
				JSONObject jsonObj = JSONObject.parseObject(userObj.toString());
	    		SellerInfo seller = JSONObject.toJavaObject(jsonObj, SellerInfo.class);
	    		
				//保存申请下架操作日志
				operLogService.addOperLog(id, "下架", "申请公众号下架", seller.getId());
				return ResponseResult.success(null);
			}else {
				return ResponseResult.fail(Constants.RESP_TOKEN_TIMEOUT, "未登录或登录超时");
			}
		}else {
			return ResponseResult.fail(Constants.RESP_FAIL, "签名校验失败");
		}		
    }
    
}
